/*
 * Copyright (c) 2021 KaiHong Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "hos_init.h"
#include "cmsis_os2.h"



#include "wifi_device.h"
#include "wifi_hotspot.h"
#include "wifi_error_code.h"
#include "lwip/netifapi.h"
#include "sta.h"
#include "softap.h"
#include "savewifi.h"


#define _PROT_ 80
#define TCP_BACKLOG 10

//在sock_fd 进行监听，在 new_fd 接收新的链接
int sock_fd, new_fd; 

char recvbuf[1024];
char *buf = "Hello! I'm BearPi-HM_Nano TCP Server!";
char *httphard1 = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: 1298\r\nConnection: close\r\n\r\n";
char *webtr = 
"<html><head><meta charset=\"UTF-8\" /><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><meta http-equiv=\"X-UA-Compatible\" content=\"ie=edge\"><title>程皖配网</title></head><body><form name=\"my\"><div align=\"center\"><font size=\"16\">欢迎使用程皖配网</font> </div><br><div align=\"center\">WiFi名称：<input type=\"text\" name=\"s\" placeholder=\"请输入您WiFi的名称\" id=\"aa\" style=\"text-align:center\"></div><br><div align=\"center\">WiFi密码：<input type=\"text\" name=\"p\" placeholder=\"请输入您WiFi的密码\" id=\"bb\"></div><br><div align=\"center\">服务器IP：<input type=\"text\" name=\"i\" placeholder=\"请输入您的服务器IP\" id=\"cc\"></div><br><div align=\"center\">服务器端口：<input type=\"text\" name=\"t\" placeholder=\"请输入您的服务器端口\" id=\"dd\"></div> <br><div align=\"center\"><input type=\"button\" value=\"连接\" onclick=\"wifi()\" style=\"width:150px;height:40px\"  ></div></form><script language=\"javascript\">function wifi(){var ssid = my.s.value;var password =my.p.value;var tcp_ip = my.i.value;var tcp_port = my.t.value;var xmlhttp=new XMLHttpRequest();xmlhttp.open(\"GET\",\"/HandleVal?ssid=\"+ssid+\"&password=\"+password+\"&tcp_ip=\"+tcp_ip+\"&tcp_port=\"+tcp_port,true);xmlhttp.send()}</script></body></html><!-- 程皖个人博客http://chengone.cn --><!-- 程皖个人博客http://chengone.cn --><!-- 程皖个人博客http://chengone.cn --><!-- 程皖个人博客http://chengone.cn --><!-- 程皖个人博客http://chengone.cn -->"
;
char *TEST = "HTTP";
char get_ssid[50];
char get_pwd[50];


/* 
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1253
Connection: close */


#define AP_SSID "lalhan"
#define AP_PSK  "0987654321"

#define ONE_SECOND 1
#define DEF_TIMEOUT 15

static void OnHotspotStaJoinHandler(StationInfo *info);
static void OnHotspotStateChangedHandler(int state);
static void OnHotspotStaLeaveHandler(StationInfo *info);


uint16_t if_get_wifi_flag;

static struct netif *g_lwip_netif = NULL;
static int g_apEnableSuccess = 0;
WifiEvent g_wifiEventHandler = {0};

WifiErrorCode error;

uint8_t Set_clint_flag=0;
static BOOL WifiAPTask(void)
{

	err_t ret;
    //延时2S便于查看日志
    osDelay(200);

    //注册wifi事件的回调函数
    g_wifiEventHandler.OnHotspotStaJoin = OnHotspotStaJoinHandler;
    g_wifiEventHandler.OnHotspotStaLeave = OnHotspotStaLeaveHandler;
    g_wifiEventHandler.OnHotspotStateChanged = OnHotspotStateChangedHandler;

    error = RegisterWifiEvent(&g_wifiEventHandler);
    if (error != WIFI_SUCCESS)
    {
        printf("RegisterWifiEvent failed, error = %d.\r\n",error);
        return -1;
    }
    printf("RegisterWifiEvent succeed!\r\n");
    //设置指定的热点配置
    HotspotConfig config = {0};

    strcpy(config.ssid, AP_SSID);
    strcpy(config.preSharedKey, AP_PSK);
    config.securityType = WIFI_SEC_TYPE_OPEN;
    config.band = HOTSPOT_BAND_TYPE_2G;
    config.channelNum = 7;

    error = SetHotspotConfig(&config);
    if (error != WIFI_SUCCESS)
    {
        printf("SetHotspotConfig failed, error = %d.\r\n", error);
        return -1;
    }
    printf("SetHotspotConfig succeed!\r\n");

    //启动wifi热点模式
    error = EnableHotspot(); 
    if (error != WIFI_SUCCESS)
    {
        printf("EnableHotspot failed, error = %d.\r\n", error);
        return -1;
    }
    printf("EnableHotspot succeed!\r\n");

    //检查热点模式是否使能
    if (IsHotspotActive() == WIFI_HOTSPOT_NOT_ACTIVE)
    {
        printf("Wifi station is not actived.\r\n");
        return -1;
    }
    printf("Wifi station is actived!\r\n");

    //启动dhcp
    g_lwip_netif = netifapi_netif_find("ap0");
    if (g_lwip_netif) 
    {
        ip4_addr_t bp_gw;
        ip4_addr_t bp_ipaddr;
        ip4_addr_t bp_netmask;

        IP4_ADDR(&bp_gw, 192, 168, 1, 1);           /* input your gateway for example: 192.168.1.1 */
        IP4_ADDR(&bp_ipaddr, 192, 168, 1, 1);       /* input your IP for example: 192.168.1.1 */
        IP4_ADDR(&bp_netmask, 255, 255, 255, 0);    /* input your netmask for example: 255.255.255.0 */

        ret = netifapi_netif_set_addr(g_lwip_netif, &bp_ipaddr, &bp_netmask, &bp_gw);
        if(ret != ERR_OK)
        {
            printf("netifapi_netif_set_addr failed, error = %d.\r\n", ret);
            return -1;
        }
        printf("netifapi_netif_set_addr succeed!\r\n");

        ret = netifapi_dhcps_start(g_lwip_netif, 0, 0);
        if(ret != ERR_OK)
        { 
            printf("netifapi_dhcp_start failed, error = %d.\r\n", ret);
            return -1;
        }
        printf("netifapi_dhcps_start succeed!\r\n");

    }

    /****************以下为UDP服务器代码***************/
	//服务端地址信息
	struct sockaddr_in server_sock;

	//客户端地址信息
	struct sockaddr_in client_sock;
	int sin_size;

	struct sockaddr_in *cli_addr;

	

	//创建socket
	if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
	{
		perror("socket is error\r\n");
		exit(1);
	}

	bzero(&server_sock, sizeof(server_sock));
	server_sock.sin_family = AF_INET;
	server_sock.sin_addr.s_addr = htonl(INADDR_ANY);
	server_sock.sin_port = htons(_PROT_);

	//调用bind函数绑定socket和地址
	if (bind(sock_fd, (struct sockaddr *)&server_sock, sizeof(struct sockaddr)) == -1)
	{
		perror("bind is error\r\n");
		exit(1);
	}

	//调用listen函数监听(指定port监听)
	if (listen(sock_fd, TCP_BACKLOG) == -1)
	{
		perror("listen is error\r\n");
		exit(1);
	}

	printf("start accept\n");

	//调用accept函数从队列中
	while (1)
	{
		sin_size = sizeof(struct sockaddr_in);

		if ((new_fd = accept(sock_fd, (struct sockaddr *)&client_sock, (socklen_t *)&sin_size)) == -1)
		{
			perror("accept");
			continue;
		}
        

		cli_addr = malloc(sizeof(struct sockaddr));

		printf("accept addr\r\n");

		if (cli_addr != NULL)
		{
			memcpy(cli_addr, &client_sock, sizeof(struct sockaddr));
            printf("\r\nthe ss is %s",cli_addr);
		}

		//处理目标
		

		while (1)
		{
			if ((ret = recv(new_fd, recvbuf, sizeof(recvbuf), 0)) == -1)
			{
				printf("recv error \r\n");
			}else
            {
            //printf("recv :%s\r\n", recvbuf);
            //返回s1中包含s2所有字符的最大起始段长度
            //size_t strspn(const char *s1, const char *s2);
            char* p= strstr(recvbuf,TEST);
            uint16_t DIR_buff = p - recvbuf;
            printf("\r\nThe GET HTTP num:%d\r\n",DIR_buff);
            if(DIR_buff<10)
            {
              Set_clint_flag = 1;

            }else if(DIR_buff>40)
            {
              Set_clint_flag = 2;


              char *p1, *p2;
              p1 = strstr(recvbuf, "ssid=");
              p2 = strstr(recvbuf, "&password");
               if(p1!=0 && p2!=0 && p1<p2)
               {
                   p1 += strlen("ssid=");
                   memcpy(get_ssid, p1, p2 - p1);
                   printf("\r\nget the ssid = %s\r\n", get_ssid);  
               }

              p1 = strstr(recvbuf, "password=");
              p2 = strstr(recvbuf, "&tcp_ip");
               if(p1!=0 && p2!=0 && p1<p2)
               {
                   p1 += strlen("password=");
                   memcpy(get_pwd, p1, p2 - p1);
                   printf("get the ssid = %s\r\n", get_pwd);  
               }
              WifiConnect(get_ssid,get_pwd);

               

            }else
            {
                Set_clint_flag = 3;
            }
            
            bzero(recvbuf, sizeof(recvbuf));
            //close(new_fd);
            }

			sleep(2);


            if(Set_clint_flag==1)
            {

        
            if ((ret = send(new_fd, httphard1, strlen(httphard1), 0)) == -1)
			{
				perror("send : ");
                
			}
			if ((ret = send(new_fd, webtr, strlen(webtr), 0)) == -1)
			{
				perror("send : ");
                
			}
                
                Set_clint_flag = 0;
                new_fd = -1;
                break;            
            }else if(Set_clint_flag==2)
            {
                Set_clint_flag = 0;
                new_fd = -1;
                WifiConnect(get_ssid,get_pwd);
                break;   
            }else if(Set_clint_flag==3)
            {
                Set_clint_flag = 0;
                new_fd = -1;
                break;      
            }
            
            

			sleep(2);
		}

        if(if_get_wifi_flag==1)
        {
            break;
        }
		
       // Set_clint_flag = 0;
	}
    
}

static void HotspotStaJoinTask(void)
{
    static char macAddress[32] = {0};
    StationInfo stainfo[WIFI_MAX_STA_NUM] = {0};
    StationInfo *sta_list_node = NULL;
    unsigned int size = WIFI_MAX_STA_NUM;

    error = GetStationList(stainfo, &size);
    if (error != WIFI_SUCCESS) {
        printf("HotspotStaJoin:get list fail, error is %d.\r\n", error);
        return;
    }
    sta_list_node = stainfo;
    for (uint32_t i = 0; i < size; i++, sta_list_node++) {
    unsigned char* mac = sta_list_node->macAddress;
    snprintf(macAddress, sizeof(macAddress), "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
    }
    g_apEnableSuccess++;
}
static void OnHotspotStaJoinHandler(StationInfo *info)
{
    if (info == NULL) {
    printf("HotspotStaJoin:info is null.\r\n");
    } 
    else {
        printf("New Sta Join\n");
        osThreadAttr_t attr;
        attr.name = "HotspotStaJoinTask";
        attr.attr_bits = 0U;
        attr.cb_mem = NULL;
        attr.cb_size = 0U;
        attr.stack_mem = NULL;
        attr.stack_size = 2048;
        attr.priority = 24;
        if (osThreadNew((osThreadFunc_t)HotspotStaJoinTask, NULL, &attr) == NULL) {
            printf("HotspotStaJoin:create task fail!\r\n");
        }
    }
    return;
}

static void OnHotspotStaLeaveHandler(StationInfo *info)
{
    if (info == NULL) {
        printf("HotspotStaLeave:info is null.\r\n");
    } 
    else {
        static char macAddress[32] = {0};
        unsigned char* mac = info->macAddress;
        snprintf(macAddress, sizeof(macAddress), "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
        printf("HotspotStaLeave: macAddress=%s, reason=%d.\r\n", macAddress, info->disconnectedReason);
        g_apEnableSuccess--;
    }
    return;
}

static void OnHotspotStateChangedHandler(int state)
{
    printf("HotspotStateChanged:state is %d.\r\n", state);
    if (state == WIFI_HOTSPOT_ACTIVE) {
        printf("wifi hotspot active.\r\n");
    } else {
        printf("wifi hotspot noactive.\r\n");
    }
}

void Wifi_AP_Demo(void)
{
    osThreadAttr_t attr;

    attr.name = "WifiAPTask";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 20240;
    attr.priority = 25;

    if (osThreadNew((osThreadFunc_t)WifiAPTask, NULL, &attr) == NULL)
    {
        printf("Falied to create WifiAPTask!\r\n");
    }
}


